<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <meta charset="utf-8">
    <title>数据库</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="./layui/css/layui.css" th:href="@{/layui/css/layui.css}" media="all">
    <link rel="stylesheet" href="./style/admin.css" th:href="@{/style/admin.css}" media="all">
    <link rel="stylesheet" href="./style/myself.css" th:href="@{/style/myself.css}" media="all">
    <!-- 让IE8/9支持媒体查询，从而兼容栅格 -->
    <!--[if lt IE 9]>
    <script src="./js/html5.min.js" th:src="@{/js/html5.min.js}"></script>
    <script src="./js/respond.min.js" th:src="@{/js/respond.min.js}"></script>
    <![endif]-->
    <script type="text/javascript" charset="utf-8" th:inline="javascript">
        let ctxPath = /*[[@{/}]]*/'';
        let authority = [[${#authorization.expression('hasAuthority("超级管理员")')}]];
    </script>
    <style type="text/css">
        #mynetwork {
            width: 600px;
            height: 600px;
        }
        *{padding: 0;margin: 0;}
        .menu{
            /*这个样式不写，右键弹框会一直显示在画布的左下角*/
            position: absolute;
            background: #ffffff;
            border-radius: 5px;
            left: -99999px;
            top: -999999px;
            z-index: 999;
        }
        .menu ul{list-style: none}
        .menu ul li{
            padding: 2.5px 10px;
            color: #659bc5;
            border-bottom: 1px solid #ffffff;
            font-size: 14px;
            cursor: pointer;
            list-style: none;
        }
        .menu ul li:hover{
            color: #659bc5;
        }
        .menu ul li:last-child{
            border-bottom: none;
            padding: 5px 10px 0 10px;
        }

        .layui-form-item .layui-input-block {
            margin-left: 0;
        }
    </style>
</head>
<body>
<div id="mynetwork" style="height:calc(100vh); width: 100%;"></div>

<!--点击节点操作-->
<div id="nodeMenuOperation" class="menu" style="display: none;">
    <ul>
        <li style="margin-top: 10px;">
            <button type="button" class="layui-btn-sm layui-btn" id="startNode">
                <i class="layui-icon layui-icon-play layui-font-12"></i>启动
            </button>
        </li>
        <li style="margin-bottom: 10px;">
            <button type="button" class="layui-btn-sm layui-btn layui-btn-danger" id="stopNode">
                <i class="layui-icon layui-icon-radio layui-font-15"></i>停止
            </button>
        </li>
    </ul>
</div>
</body>
<script type="text/javascript" th:src="@{/js/vis-network.min.js}"></script>
<script src="./layui/layui.js" th:src="@{/layui/layui.js}" charset="utf-8"></script>
<script charset="utf-8" th:inline="javascript">
    layui.config({
        base: ctxPath //静态资源所在路径
    }).extend({
        index: 'lib/index' //主入口模块
    }).use(['index', 'element', 'layer', 'form', 'jquery', 'util'], function () {
        let admin = layui.admin;
        let form = layui.form;
        let $ = layui.$
        let clickNodeList = {id: 1}, clickEdgesList = {id: 1};

        // 创建节点数据数组
        let index = layer.load(0, {shade: false}); //0代表加载的风格，支持0-2

        // 获取容器
        let container = document.getElementById('mynetwork');

        // 将数据赋值给vis 数据格式化器
        let visData = {
            nodes: [],
            edges: []
        };

        let options = {
            physics: {
                enabled: true,
                barnesHut: {
                    gravitationalConstant: -2000,
                    centralGravity: 0.3,
                    springLength: 950,
                    springConstant: 0.04,
                    damping: 0.09,
                    avoidOverlap: 0.1
                },
                maxVelocity: 146,
                minVelocity: 0.1,
                solver: 'barnesHut',
                timestep: 0.35,
                stabilization: {
                    enabled: true,
                    iterations: 2000,
                    updateInterval: 25
                }
            },
            //固定布局，保证每次渲染的位置都一样
            layout: {
                randomSeed: 1024
            },
            //设置节点
            nodes: {
                size: 18,
                font: {
                    color: 'black',
                    align: 'left',
                    size: 11,
                    vadjust: -10, // 将文字向上移动15个像素
                    strokeWidth: 0.2, // 描边宽度
                    strokeColor : 'black' // 描边颜色
                }
            },
            edges: {
                arrows: 'middle',
                dashes: true,//虚线
                width: 2,  // 设置默认的边宽度为3
                smooth: {
                    //设置两个节点之前的连线的状态
                    enabled: true //默认是true，设置为false之后，两个节点之前的连线始终为直线，不会出现贝塞尔曲线
                },
                //箭头
                arrows: {
                    to: {
                        enabled: true,
                        scaleFactor: 0.5,
                        type: "arrow"
                    },
                    middle: {
                        enabled: true,
                        scaleFactor: 0.5,
                        type: "arrow"
                    }
                }
            }
        };
        // 初始化关系图
        let network = new vis.Network(container, visData, options);

        //点击的判断是否选中节点时候显示隐藏
        network.on('click', function (properties) {
            if (properties.nodes.length > 0) {
                clickNodeList = getNode(properties.nodes[0]);
                if (typeof (clickNodeList) == "undefined") {
                    $('#nodeMenuOperation').hide();
                } else {
                    $('#nodeMenuOperation').css({
                        'display': 'block',
                        'left': properties.event.center.x + 15,
                        'top': properties.event.center.y + 15
                    });
                }
            } else if (properties.edges.length > 0) {
                clickEdgesList = getEdge(properties.edges[0]);
            } else {
                //点击画布，不是节点，不是线，隐藏div
                $("#nodeMenuOperation").hide();
                $("#edgeMenuOperation").hide();
            }
        });

        // 随机生成虚线间隔长度
        function getRandomDashes() {
            let dashes = [];
            for (let i = 0; i < 5; i++) {
                dashes.push(Math.random() * 5);
            }
            return dashes;
        }
        //线条动画
        setInterval(function() {
            let newDashes = getRandomDashes();
            network.body.data.edges.forEach(function (edge) {
                network.body.data.edges.update({ id: edge.id, width: 3, dashes: newDashes}); // 更新边的宽度
            })
        }, 150);

        $(document).ready(function() {
            // 这里写你的初始化代码
            loadData()
        });

        async function loadData(){
            admin.req({
                type: 'get',
                url: ctxPath + 'dataLink/getDataLink?showName=' + localStorage.getItem("showName"),
                dataType: 'json',
                headers: {
                    [[${_csrf.headerName}]]: [[${_csrf.token}]]
                },
                success: function (result) {
                    localStorage.removeItem("showName")
                    let resData = result.data;
                    let promises = []; // 用于存储所有的Promise
                    for (let i = 0; i < resData.links.length; i++) {
                        if(resData.links[i].color == 'red'){
                            let promise = new Promise((resolve, reject) => {
                                admin.req({
                                    type: 'get',
                                    url: ctxPath + 'dataLink/getErrMsg',
                                    data: {from : resData.links[i].from,
                                        to : resData.links[i].to,
                                        label : resData.links[i].label
                                    },
                                    dataType: 'json',
                                    headers: {
                                        [[${_csrf.headerName}]]: [[${_csrf.token}]]
                                    },
                                    success: function (result) {
                                        let info = "";
                                        for (let j = 0; j < result.data.length; j++) {
                                            info = info + result.data[j].message;
                                        }
                                        resData.links[i].label = info
                                        resolve(); // 请求成功后resolve这个Promise
                                    },
                                    error: function (error) {
                                        reject(error); // 请求失败后reject这个Promise
                                    }
                                })
                            });

                            promises.push(promise); // 将这个Promise添加到数组中
                        }
                    }
                    Promise.all(promises).then(() => {
                        // 这里的代码会在所有的admin.req请求完成后执行
                        network.setData({
                            nodes: resData.nodes,
                            edges: resData.links
                        });

                        visData.nodes = resData.nodes
                        visData.edges = resData.links

                        layer.close(index);
                    });
                },
                error: function () {
                    localStorage.removeItem("showName")
                    layer.close(index);
                    layer.msg('系统错误！', {icon: 5, shift: 6});
                }
            });
        }

        //获取节点 获取线
        function getNode(option) {
            for (let i = 0; i < visData.nodes.length; i++) {
                if (option == visData.nodes[i].id) {
                    return visData.nodes[i];
                }
            }
        }
        function getEdge(option) {
            for (let i = 0; i < visData.edges.length; i++) {
                if (option == visData.edges[i].id) {
                    return visData.edges[i];
                }
            }
        }

        //按钮
        $('#startNode').off('click').on('click', function(){
            layer.open({
                type: 1,
                title: '启动节点（' + clickNodeList.id + '）',
                area: ['25%', 'auto'],
                content: `
                                        <form class="layui-form" style="margin: 15px;">
                                            <div class="layui-form-item">
                                                <div class="layui-input-block">
                                                    <input type="text" name="username" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
                                                </div>
                                            </div>
                                            <div class="layui-form-item">
                                                <div class="layui-input-block">
                                                    <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
                                                </div>
                                            </div>
                                            <div class="layui-form-item">
                                                <input type="hidden" name="type" value="0">
                                            </div>
                                            <div class="layui-form-item">
                                                <div class="layui-input-block">
                                                    <button class="layui-btn" lay-submit lay-filter="operateNode">执行</button>
                                                </div>
                                            </div>
                                        </form>
                                    `
            });
        });
        $('#stopNode').off('click').on('click', function(){
            layer.open({
                type: 1,
                title: '停止节点（' + clickNodeList.id + '）',
                area: ['25%', 'auto'],
                content: `
                                            <form class="layui-form" style="margin: 15px;">
                                                <div class="layui-form-item">
                                                    <div class="layui-input-block">
                                                        <input type="text" name="username" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
                                                    </div>
                                                </div>
                                                <div class="layui-form-item">
                                                    <div class="layui-input-block">
                                                        <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
                                                    </div>
                                                </div>
                                                <div class="layui-form-item">
                                                    <input type="hidden" name="type" value="1">
                                                </div>
                                                <div class="layui-form-item">
                                                    <div class="layui-input-block">
                                                        <button class="layui-btn" lay-submit lay-filter="operateNode">执行</button>
                                                    </div>
                                                </div>
                                            </form>
                                        `
            });
        });

        //启动和停止节点线程
        form.on('submit(operateNode)', function(data){
            let $this = $(this);
            $this.html('<i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i> 执行中...');
            $this.prop('disabled', true); // 禁用按钮
            data.field.ip = clickNodeList.id
            let info = data.field

            admin.req({
                type: 'post',
                url: ctxPath + 'dataLink/operateNode',
                data: {info: JSON.stringify(info)},
                dataType: 'json',
                headers: {
                    [[${_csrf.headerName}]]: [[${_csrf.token}]]
                },
                success: function (result) {
                    layer.close(1);
                    let msg = "";
                    if(result.code == 200){
                        msg = "执行成功";
                    }else{
                        msg = "执行失败";
                    }
                    layer.msg(msg);
                    $this.html('执行');
                    $this.prop('disabled', false); // 启用按钮
                }
            })
            // 阻止表单跳转
            return false;
        });

    })
</script>
</body>
</html>
